package httpserver

import (
	"io"
	"net/http"
	"os"

	_ "example.com/dcache/docs"
	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
)

// InitRouter initialize routing information
func InitRouter() *gin.Engine {
	gin.DisableConsoleColor()

	ginLogPath := "./logger/all.log"
	_, err := os.Stat(ginLogPath)
	if err != nil && os.IsNotExist(err) {
		f, _ := os.Create(ginLogPath)
		gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
	}

	f, _ := os.OpenFile(ginLogPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm|os.ModeAppend)
	gin.DefaultWriter = io.MultiWriter(f, os.Stdout)

	r := gin.New()
	r.Use(
		gin.LoggerWithWriter(gin.DefaultWriter, "/1.0/ping"),
		gin.Recovery(),
	)

	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	g0 := r.Group("/1.0")
	{
		//HeartBeat interface
		g0.GET("/ping", func(c *gin.Context) {
			c.String(http.StatusOK, "pong")
		})

		/* Group localApi provides the http server interfaces,
		   operate data on a target node */
		g1 := g0.Group("/localApi")
		{
			//POST create a group
			g1.POST("/Groups/:groupName", setGroupLocal)

			//DELETE delete a group
			g1.DELETE("/Groups/:groupName", deleteGroupLocal)

			//POST set a k-v
			g1.POST("/keys/:groupName/:key/:value", setLocal)

			//PUT update a key's value
			g1.PUT("/keys/:groupName/:key/:value", setLocal)

			//GET get a key's value
			g1.GET("/keys/:groupName/:key", getLocal)

			//DELETE delete a k-v
			g1.DELETE("/keys/:groupName/:key", deleteLocal)
		}

		/* Group api provides the http server interfaces */
		g2 := g0.Group("/api")
		{
			g2.GET("/getAllElements/:groupName", getAllElements)

			//POST create a group
			g2.POST("/Groups/:groupName", setGroups)

			//GET get all groups
			g2.GET("/Groups", getAllGroups)

			//DELETE delete a group
			g2.DELETE("/Groups/:groupName", deleteGroup)

			//POST create a k-v
			g2.POST("/keys", setOnTargetNode)

			//PUT update a key's value
			g2.PUT("/keys", setOnTargetNode)

			//GET get a key's value
			g2.GET("/keys", getOnTargetNode)

			//DELETE delete a k-v
			g2.DELETE("/keys", deleteOnTargetNode)
		}

		/* Group api provides the http server interfaces */
		g3 := g0.Group("/util")
		{
			g3.POST("/updateGlobalNodesList", updateGlobalNodesList)
		}
	}

	return r
}
